/* eslint-disable no-plusplus */
/* eslint-disable no-underscore-dangle */

const defaultOptions = {
  strokeColor: '#000',
  strokeWidth: 4,
  lineDash: [],
  mode: 'free',
}

function Drawing(options) {
  this.canvas = options.canvas;
  this.strokeColor = options.strokeColor || defaultOptions.strokeColor;
  this.strokeWidth = options.strokeWidth || defaultOptions.strokeWidth;
  this.lineDash = options.lineDash || defaultOptions.lineDash; // 画直线模式下，设置虚线参数
  this.mode = options.mode || defaultOptions.mode; // 自由绘画 或 直线
  this.lineJoin = 'round';

  this.onAddStroke = typeof options.onAddStroke === 'function' ? options.onAddStroke : null;

  this.drawingCtx = this.canvas.getContext('2d');

  this._isDrawing = false;
  this._stroke = null;
  this._strokes = [];

  this.canvas.addEventListener('mousedown', e => this._beginStroke(e));
  this.canvas.addEventListener('mousemove', e => this._draw(e));
  this.canvas.addEventListener('mouseup', e => this._endStroke(e));
  this.canvas.addEventListener('mouseleave', e => this._endStroke(e));
  this.canvas.addEventListener('touchstart', e => this._beginStroke(e));
  this.canvas.addEventListener('touchmove', e => this._draw(e));
  this.canvas.addEventListener('touchend', e => this._endStroke(e));
  this.canvas.addEventListener('touchleave', e => this._endStroke(e));
}

Drawing.prototype = {
  setStrokeColor(color) {
    this.strokeColor = color;
  },
  setStrokeWidth(width) {
    this.strokeWidth = width;
  },
  setLineDash(lineDash) {
    this.lineDash = lineDash;
  },
  setMode(mode) {
    this.mode = mode;
  },
  refresh(strokes) {
    this.canvas.width = this.canvas.width;
    this._strokes = strokes;
    this._strokes.forEach((stroke, index) => {
      const { color, width, lineDash, plots } = stroke;
      if (plots.length < 2) return;
      this.drawingCtx.lineWidth = width;
      this.drawingCtx.strokeStyle = color;
      this.drawingCtx.setLineDash(lineDash || []);
      this.drawingCtx.beginPath();
      this.drawingCtx.moveTo(plots[0][0], plots[0][1]);
      for (let i = 1; i < plots.length; i++) {
        this.drawingCtx.lineTo(plots[i][0], plots[i][1]);
      }
      this.drawingCtx.stroke();
    });
  },
  _beginStroke(e) {
    e.preventDefault(); // 阻止浏览器默认行为，例如在平板上会触发往下拖动整个浏览器页面。
    this._isDrawing = true;
    this.canvasBoundingRect = this.canvas.getBoundingClientRect();
    const clientX = e.touches && e.touches[0] ? e.touches[0].clientX : e.clientX;
    const clientY = e.touches && e.touches[0] ? e.touches[0].clientY : e.clientY;
    const p = [
      Math.round(clientX - this.canvasBoundingRect.left),
      Math.round(clientY - this.canvasBoundingRect.top)
    ];
    this._stroke = {
      color: this.strokeColor,
      width: this.strokeWidth,
      plots: [p]
    };
    if (this.mode === 'line' && this.lineDash && this.lineDash.length !== 0) {
      this._stroke.lineDash = this.lineDash;
    }
    this.drawingCtx.lineWidth = this.strokeWidth;
    this.drawingCtx.strokeStyle = this.strokeColor;
    this.drawingCtx.setLineDash(this._stroke.lineDash || []);
    this.drawingCtx.lineJoin = this.lineJoin;
    this.drawingCtx.beginPath();
    this.drawingCtx.moveTo(p[0], p[1]);
  },

  _endStroke(e) {
    if (!this._isDrawing) return;
    e.preventDefault();
    if (this.onAddStroke) this.onAddStroke(this._stroke);
    this._isDrawing = false;
    this._stroke = null;
  },

  _draw(e) {
    if (!this._isDrawing) return;
    e.preventDefault();
    const clientX = e.touches && e.touches[0] ? e.touches[0].clientX : e.clientX;
    const clientY = e.touches && e.touches[0] ? e.touches[0].clientY : e.clientY;
    const p = [
      Math.round(clientX - this.canvasBoundingRect.left),
      Math.round(clientY - this.canvasBoundingRect.top)
    ];
    if (this.mode === 'line') {
      this.refresh(this._strokes);
      this._stroke.plots[1] = p;
      this.drawingCtx.lineWidth = this.strokeWidth;
      this.drawingCtx.strokeStyle = this.strokeColor;
      this.drawingCtx.setLineDash(this._stroke.lineDash || []);
      this.drawingCtx.lineJoin = this.lineJoin;
      this.drawingCtx.beginPath();
      this.drawingCtx.moveTo(this._stroke.plots[0][0], this._stroke.plots[0][1]);
      this.drawingCtx.lineTo(this._stroke.plots[1][0], this._stroke.plots[1][1]);
      this.drawingCtx.stroke();
    } else {
      this.drawingCtx.lineTo(p[0], p[1]);
      this.drawingCtx.stroke();
      const prevPoint = this._stroke.plots[this._stroke.plots.length - 1];
      if (!prevPoint || !(prevPoint[0] === p[0] && prevPoint[1] === p[1])) {
        // 相同的坐标不存储
        this._stroke.plots.push(p);
      }
    }
  }
}

export default Drawing;
